import java_cup.runtime.*;


/**
 * This class is a simple example lexer.
 */
%%

%class Lexer
%unicode
%cup
%line
%column

%{

  private int line = 1;
  private boolean debugFlag = false;

  private Symbol symbol(String debug, int type) {
  	if (debugFlag) System.out.print(debug);
    return new Symbol(type, yyline, yycolumn);
  }
  private Symbol symbol(String debug, int type, Object value) {
  	if (debugFlag) System.out.print(debug);
    return new Symbol(type, yyline, yycolumn, value);
  }
  
%}

delim	= [ \t\r]
ws		= {delim}+
letter	= [A-Za-z]
digit	= [0-9]
id		= [_]*{letter}({letter}|{digit})*
integer = (\-)?({digit})+
real	= (\-)?{digit}+(\.){digit}+(E[+-]?{digit}+)?
string	= \"({letter}|{digit})*\"
comment = [\-][\-]~[\r]
collections = "Bag" | "Set" | "Sequence"
boolean = true | false
context = "context" | "Context"

%%

"package"	 {return symbol("(PACKAGE)", sym.PACKAGE);}
"endpackage" {return symbol("(ENDPACKAGE)", sym.ENDPACKAGE);}

{context}	{return symbol("(CONTEXT)", sym.CONTEXT);}
"pre"		{return symbol("(PRE)", sym.PRE);}
"post"		{return symbol("(POST)", sym.POST);}

"->"		{return symbol("(ARROW)", sym.ARROW);}
":"			{return symbol("(COLON)", sym.COLON);}
"::"		{return symbol("(DCOLON)", sym.DCOLON);}
".."		{return symbol("(DOTDOT)", sym.DOTDOT);}

"and"		{return symbol("(AND)", sym.AND);}
"or"		{return symbol("(OR)", sym.OR);}
"xor"		{return symbol("(XOR)", sym.XOR);}
"not"		{return symbol("(NOT)", sym.NOT);}

"<>"		{return symbol("(DIFF)", sym.DIFF);}
"<"			{return symbol("(LT)", sym.LT);}
">"			{return symbol("(GT)", sym.GT);}
"<="		{return symbol("(LE)", sym.LE);}
">="		{return symbol("(GE)", sym.GE);}
"=" 		{return symbol("(EQ)", sym.EQ);}

"if" 		{return symbol("(IF)", sym.IF);}
"then"		{return symbol("(THEN)", sym.THEN);}
"else"		{return symbol("(ELSE)", sym.ELSE);}
"endif"		{return symbol("(ENDIF)", sym.ENDIF);}


{collections} {return symbol("(COLLECTION)", sym.COLLECTION, yytext());}
"select"	{return symbol("(SELECT)", sym.SELECT);}
"exists"	{return symbol("(EXISTS)", sym.EXISTS);}
"forAll"	{return symbol("(FORALL)", sym.FORALL);}
"size"		{return symbol("(SIZE)", sym.SIZE);}
"implies"	{return symbol("(IMPLIES)", sym.IMPLIES);}
"including"	{return symbol("(INCLUDING)", sym.INCLUDING);}
"excluding"	{return symbol("(EXCLUDING)", sym.EXCLUDING);}
"includes"	{return symbol("(INCLUDES)", sym.INCLUDES);}
"excludes"	{return symbol("(EXCLUDES)", sym.EXCLUDES);}
"@pre"		{return symbol("(ATPRE)", sym.ATPRE);}
"result"	{return symbol("(RESULT)", sym.RESULT);}

"("			{return symbol("(LPAREN)", sym.LPAREN);}
")"			{return symbol("(RPAREN)", sym.RPAREN);}
"["			{return symbol("(LBRAC)", sym.LBRAC);}
"]"			{return symbol("(RBRAC)", sym.RBRAC);}
"{"			{return symbol("(LCURLY)", sym.LCURLY);}
"}"			{return symbol("(RCURLY)", sym.RCURLY);}	
","			{return symbol("(COMMA)", sym.COMMA);}
"."			{return symbol("(DOT)", sym.DOT);}
";"			{return symbol("(SEMICOLON)", sym.SEMICOLON);}
"|"			{return symbol("(PIPE)", sym.PIPE);}

"+"			{return symbol("(PLUS)", sym.PLUS, "+");}
"-"			{return symbol("(MINUS)", sym.MINUS, "-");}
"*"			{return symbol("(MULTIPLY)", sym.MULTIPLY, "*");}
"/"			{return symbol("(DIVIDE)", sym.DIVIDE, "/");}

"\n"		{line++; if (debugFlag) { System.out.println(); System.out.print(line + " > ");}}
"\R"		{line++; if (debugFlag) { System.out.println(); System.out.print(line + " > ");}}
{ws}		{}

"boolean"	{return symbol("(BOOLEANTYPE)", sym.BOOLEANTYPE);}
"void"		{return symbol("(VOID)", sym.VOID);}
"integer"	{return symbol("(INTTYPE)", sym.INTTYPE);}
"real"		{return symbol("(REALTYPE)", sym.REALTYPE);}

{boolean}	{return symbol("(BOOLEAN, " + yytext() + ")", sym.BOOLEAN, new Boolean(yytext()));}
{id}		{return symbol("(ID, " + yytext() + ")", sym.ID, yytext());}
{string}	{return symbol("(STRING, " + yytext() + " )", sym.STRING, yytext());}
{real}		{return symbol("(REAL, " + yytext() + " )", sym.REAL, new Double(yytext()));}
{integer}	{return symbol("(INT, " + yytext() + " )", sym.INTEGER, new Integer(yytext()));}
{comment}	{}


<<EOF>> {return symbol("(EOF)", sym.EOF);}
. { throw new RuntimeException("Error in line " + (line) + ", column " + (yycolumn+1) + " : Lexic error"); }